/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package GUI.Dialogs;

import GUI.Components.BButton;
import GUI.Components.BTextField;
import GUI.Components.BToggleButton;
import General.CurrentData;
import com.jme3.asset.AssetManager;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.post.Filter;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.SceneProcessor;
import com.jme3.renderer.Camera;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.Renderer;
import com.jme3.renderer.ViewPort;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.scene.Node;
import com.jme3.texture.FrameBuffer;
import com.jme3.texture.Image;
import com.jme3.util.BufferUtils;
import com.jme3.util.Screenshots;
import com.sun.awt.AWTUtilities;
import other.ElementToObjectConverter;
import other.ObjectToElementConverter;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.image.BufferedImage;
import java.nio.ByteBuffer;
import java.util.List;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import org.jdesktop.swingx.VerticalLayout;
import se.datadosen.component.RiverLayout;

public class AdditionalCameraDialog extends BasicDialog implements SceneProcessor
{

    private CameraPanel camPanel = new CameraPanel();
    private ControlPanel controlPanel;
    private Camera camera;
    private ByteBuffer byteBuffer;
    private BufferedImage image;
    private FrameBuffer frameBuffer;
    private int width, height;
    private Renderer renderer;
    private ViewPort viewPort;
    private FilterPostProcessor filterPostProcessor;
    private Node node;
    private boolean pause = false;
    private AssetManager assetManager;
    private RenderManager renderManager;
    private Point windowLocation;
    private int number = 0, reloadTime = 400;
    private Node representative;
    private boolean initialized = false;

    public AdditionalCameraDialog(Point loc,
            Vector3f location,
            Quaternion rot,
            int w,
            int h,
            Renderer render,
            RenderManager rManager,
            Node n,
            AssetManager aManager,
            List<Filter> filters,
            boolean onTop,
            int nmbr)
    {
        number = nmbr;
        windowLocation = loc;
        filterPostProcessor = new FilterPostProcessor(aManager);
        for (Filter filter : filters)
        {
            filterPostProcessor.addFilter(filter);
        }
        init(location, rot, w, h, render, rManager, n, aManager, onTop);
    }

    public AdditionalCameraDialog(
            Vector3f location,
            Quaternion rot,
            int w,
            int h,
            Renderer render,
            RenderManager rManager,
            Node n,
            AssetManager aManager,
            boolean onTop)
    {
        filterPostProcessor = new FilterPostProcessor(aManager);
        init(location, rot, w, h, render, rManager, n, aManager, onTop);
    }

    public void init(
            Vector3f location,
            Quaternion rot,
            int w,
            int h,
            Renderer render,
            RenderManager rManager,
            Node n,
            AssetManager aManager,
            final boolean onTop)
    {
        renderManager = rManager;
        assetManager = aManager;
        node = n;
        width = w;
        height = h;
        representative = (Node) assetManager.loadModel("Models/cam.j3o");
        representative.setName("cam");
        representative.setLocalTranslation(location);
        representative.setLocalRotation(rot);
        representative.setUserData("angles", new Vector3f());
        camera = new Camera(width, height);
        camera.setRotation(representative.getLocalRotation());
        camera.setFrustumPerspective(45f, 1f, 1f, 1000f);
        camera.setViewPort(0, 1, 0, 1);
        AWTUtilities.setWindowOpacity(this, 1f);
        if (number == 0)
        {
            number = CurrentData.getEditorWindow().getB3DApplication().getAdditionalCameraDialogs().size() + 1;
        }
        setTitle("Cam " + number);
        setModal(false);
        frameBuffer = new FrameBuffer(width, height, 1);
        frameBuffer.setDepthBuffer(Image.Format.Depth);
        frameBuffer.setColorBuffer(Image.Format.RGB8);
        renderer = render;
        image = new BufferedImage(width, height,
                BufferedImage.TYPE_4BYTE_ABGR);
        byteBuffer = BufferUtils.createByteBuffer(width * height * 4);
        viewPort = renderManager.createPostView("Offscreen View", camera);
        viewPort.setClearFlags(true, true, true);
        viewPort.setOutputFrameBuffer(frameBuffer);
        viewPort.addProcessor(this);
        viewPort.addProcessor(filterPostProcessor);
        viewPort.attachScene(node);
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                AdditionalCameraDialog.this.setAlwaysOnTop(onTop);
                camPanel.setPreferredSize(new Dimension(width, height));
                getContentPane().add(camPanel, BorderLayout.CENTER);
                controlPanel = new ControlPanel();
                getContentPane().add(controlPanel, BorderLayout.EAST);
                addWindowListener(new WindowListener()
                {
                    public void windowOpened(WindowEvent e)
                    {
                    }

                    public void windowClosing(WindowEvent e)
                    {
                        CurrentData.getEditorWindow().getB3DApplication().removeAdditionalCamera(AdditionalCameraDialog.this);
                    }

                    public void windowClosed(WindowEvent e)
                    {
                    }

                    public void windowIconified(WindowEvent e)
                    {
                    }

                    public void windowDeiconified(WindowEvent e)
                    {
                    }

                    public void windowActivated(WindowEvent e)
                    {
                    }

                    public void windowDeactivated(WindowEvent e)
                    {
                    }
                });
                setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                pack();
                if (windowLocation == null)
                {
                    setLocationRelativeTo(null);
                } else
                {
                    setLocation(windowLocation);
                }
                setResizable(false);
                setVisible(true);
                toFront();
                initialized = true;
            }
        });
        CurrentData.getEditorWindow().getB3DApplication().addAdditionalCamera(this);
    }

    private class CameraPanel extends JPanel
    {

        @Override
        public void paintComponent(Graphics gfx)
        {
            super.paintComponent(gfx);
            synchronized (image)
            {
                gfx.drawImage(image, 0, 0, null);
            }
        }
    }

    public void updateImg()
    {
        byteBuffer.clear();
        renderer.readFrameBuffer(frameBuffer, byteBuffer);
        synchronized (image)
        {
            Screenshots.convertScreenShot(byteBuffer, image);
        }
        if (camPanel != null)
        {
            camPanel.repaint();
        }
        if (filterPostProcessor.getFilterList().size()
                != CurrentData.getEditorWindow().getB3DApplication().getFilterPostProcessor().getFilterList().size()
                || reloadTime == 0)
        {
            reloadTime = 500;
            viewPort.setBackgroundColor(CurrentData.getEditorWindow().getB3DApplication().getViewPort().getBackgroundColor());
            filterPostProcessor.removeAllFilters();
            for (Filter filter : CurrentData.getEditorWindow().getB3DApplication().getFilterPostProcessor().getFilterList())
            {
                filterPostProcessor.addFilter(ElementToObjectConverter.convertFilter(ObjectToElementConverter.convertFilter(filter)));
            }
        } else
        {
            reloadTime--;
        }
    }

    @Override
    public void initialize(RenderManager rm, ViewPort vp)
    {
    }

    @Override
    public void reshape(ViewPort vp, int w, int h)
    {
    }

    @Override
    public boolean isInitialized()
    {
        return true;
    }

    @Override
    public void preFrame(float tpf)
    {
    }

    @Override
    public void postQueue(RenderQueue rq)
    {
    }

    @Override
    public void postFrame(FrameBuffer out)
    {
        if (isVisible() && !pause)
        {
            updateImg();
            camera.setLocation(representative.getWorldTranslation());
            camera.setRotation(representative.getWorldRotation());
        }
    }

    @Override
    public void cleanup()
    {
    }

    public class ControlPanel extends JPanel
    {

        private JCheckBox alwaysOnTopButton = new JCheckBox("On Top", AdditionalCameraDialog.this.isAlwaysOnTop());
        private BToggleButton continuePauseButton = new BToggleButton("Pause", true);
        private BButton sizeButton = new BButton("Size");
        private JCheckBox filterCheckBox = new JCheckBox("Show Filters");

        public ControlPanel()
        {
            setPreferredSize(new Dimension(140, 0));
            alwaysOnTopButton.addActionListener(new ActionListener()
            {
                public void actionPerformed(ActionEvent e)
                {
                    AdditionalCameraDialog.this.setAlwaysOnTop(alwaysOnTopButton.isSelected());
                }
            });
            continuePauseButton.addActionListener(new ActionListener()
            {
                public void actionPerformed(ActionEvent e)
                {
                    if (continuePauseButton.isSelected())
                    {
                        continuePauseButton.setText("Pause");
                        pause = false;
                    } else
                    {
                        continuePauseButton.setText("Continue");
                        pause = true;
                    }
                }
            });
            sizeButton.addActionListener(new ActionListener()
            {
                public void actionPerformed(ActionEvent e)
                {
                    new SizeDialog();
                }
            });
            setLayout(new VerticalLayout());
            add(alwaysOnTopButton);
            add(continuePauseButton);
            add(sizeButton);
            add(filterCheckBox);
        }

        public JCheckBox getFilterCheckBox()
        {
            return filterCheckBox;
        }

        private class SizeDialog extends BasicDialog
        {

            private BTextField widthField = new BTextField("Integer");
            private BTextField heightField = new BTextField("Integer");
            private BButton okButton = new BButton("Ok");

            public SizeDialog()
            {
                setAlwaysOnTop(true);
                widthField.setText("" + width);
                heightField.setText("" + height);
                okButton.addActionListener(new ActionListener()
                {
                    public void actionPerformed(ActionEvent e)
                    {
                        dispose();
                        AdditionalCameraDialog.this.dispose();
                        respawn(Integer.parseInt(widthField.getText()), Integer.parseInt(heightField.getText()));
                        CurrentData.getEditorWindow().getB3DApplication().removeAdditionalCamera(AdditionalCameraDialog.this);
                    }
                });
                setTitle("Set Size");
                setLayout(new RiverLayout());
                add(new JLabel("Width: "));
                add("tab hfill", widthField);
                add("br", new JLabel("Height: "));
                add("tab hfill", heightField);
                add("br right", okButton);
                pack();
                setLocation(AdditionalCameraDialog.this.getLocation());
                setVisible(true);
            }
        }
    }

    public int getNumber()
    {
        return number;
    }

    public void setNumber(int number)
    {
        this.number = number;
    }

    public Camera getCamera()
    {
        return camera;
    }

    public Node getRepresentative()
    {
        return representative;
    }

    public ControlPanel getControlPanel()
    {
        return controlPanel;
    }

    public ViewPort getViewPort()
    {
        return viewPort;
    }

    public FilterPostProcessor getFilterPostProcessor()
    {
        return filterPostProcessor;
    }

    private void respawn(int w, int h)
    {
        pause = true;
        new AdditionalCameraDialog(
                getLocation(),
                camera.getLocation(),
                camera.getRotation(),
                w,
                h,
                renderer,
                renderManager,
                node,
                assetManager,
                filterPostProcessor.getFilterList(),
                isAlwaysOnTop(),
                getNumber());
        CurrentData.getEditorWindow().getTree().sync();
    }

    public boolean initialized()
    {
        return initialized;
    }
}
